import os

from PyQt5.Qt import *
from PyQt5 import QtCore, QtGui
from PyQt5.QtCore import Qt

from config.config import Config
from controllers.MindMapEdge import Edge
from sub_window.leaf_form import LeafNodeFormWindow
from sub_window.node_form import NodeFormWindow
from views.get_node_info import get_node_info


class SmallRectNode(QGraphicsRectItem):
    def __init__(self, x, y, width, height, parent=None, scene=None, is_top=False):
        super(SmallRectNode, self).__init__(x, y, width, height, parent)
        self.setBrush(QBrush(QColor(250, 150, 100)))
        self.edges = []
        self.parent = parent
        self.scene = scene
        self.current_edge = None
        self.start_node = None
        self.is_top = is_top
        self.setAcceptHoverEvents(True)
        self.setFlag(QGraphicsRectItem.ItemIsSelectable)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            scene_pos = event.scenePos()
            self.start_node = self.scene.itemAt(scene_pos, QTransform())
            if isinstance(self.start_node, SmallRectNode) and not self.is_top:
                self.current_edge = Edge(self.start_node.parent, self.start_node)
                self.scene.addItem(self.current_edge)
                self.scene.add_item_with_undo(self.current_edge)
                super(SmallRectNode, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        scene_pos = event.scenePos()
        if self.current_edge:
            line = self.current_edge.line()
            p1x = self.start_node.scenePos().x()
            p1y = self.start_node.scenePos().y()
            width = self.start_node.rect().width()
            height = self.start_node.rect().height()
            p1 = QPointF(p1x + width / 2, p1y + height / 2)
            line.setP1(p1)
            line.setP2(scene_pos)
            self.current_edge.setLine(line)
            super(SmallRectNode, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        if self.current_edge:
            scene_pos = event.scenePos()
            target_item = None
            for item in self.scene.items(scene_pos):
                if (isinstance(item, (SmallRectNode, SubNode))
                        and item is not self.start_node.parent
                        and item is not self.start_node.parent.small_rect_bottom
                        and item is not self.start_node.parent.small_rect_top):
                    target_item = item
                    break
            if target_item:
                if isinstance(target_item, SmallRectNode):
                    target_item = target_item.parent
                self.current_edge.dest_node = target_item
                self.current_edge.update_position()
                self.current_edge.track_node()
                self.parent.child_node.add(target_item)
                target_item.parent_node.add(self.parent)
                self.current_edge = None
            else:
                self.scene.removeItem(self.current_edge)
                self.current_edge = None  # 释放鼠标初始化连线，否则会崩溃
        super(SmallRectNode, self).mouseReleaseEvent(event)

    def hoverEnterEvent(self, event):
        # 鼠标悬浮事件
        if not self.is_top:
            self.setCursor(QCursor(Qt.CrossCursor))
            super(SmallRectNode, self).hoverEnterEvent(event)

    def hoverLeaveEvent(self, event):
        # 鼠标离开事件
        if not self.is_top:
            self.setCursor(QCursor(Qt.ArrowCursor))
            super(SmallRectNode, self).hoverLeaveEvent(event)


class MyNode(QGraphicsRectItem):
    def __init__(self, x, y, width, height, scene=None, plain_text='Rect Node'):
        super(MyNode, self).__init__(x, y, width, height)
        self.setBrush(QBrush(QColor(189, 232, 255)))

        self.setFlag(QGraphicsRectItem.ItemIsMovable, True)
        self.setFlag(QGraphicsRectItem.ItemIsSelectable, True)
        self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
        self.setAcceptHoverEvents(True)

        self.parent_node = set()
        self.child_node = set()
        self.scene = scene
        # 设置文本
        self.plain_text = plain_text
        self.text = TextNode(self.plain_text, self)
        self.text.setDefaultTextColor(Qt.black)
        self.text.setPos(x + width / 2 - self.text.boundingRect().width() / 2,
                         y + height / 2 - self.text.boundingRect().height() / 2)

        self.edges = []  # 储存链接到该节点的连线
        self.text.document().contentsChanged.connect(self.updateRectSize)

        self.leaf_info = get_node_info(self.text)
        self.node_info = {}

    def updateRectSize(self):
        # 确保矩形的最小宽度
        text_width = max(100, self.text.boundingRect().width()+15)
        text_height = max(50, self.text.boundingRect().height()+15)

        self.setRect(self.rect().x(), self.rect().y(), text_width, text_height)
        self.text.setPos(self.rect().x() + text_width / 2 - self.text.boundingRect().width() / 2,
                         self.rect().y() + text_height / 2 - self.text.boundingRect().height() / 2)
        self.update_small_node_pos(text_width, text_height)
        for edge in self.edges:
            edge.update_position()


    def paint(self, painter, option, widget=None):
        # 使用圆角矩形
        painter.setBrush(self.brush())
        painter.setPen(self.pen())
        rect = QRectF(self.rect())
        painter.drawRoundedRect(rect, 10, 10)

        if self.isSelected():
            # 设置额外边框的样式
            self.setBrush(QBrush(QColor(95, 214, 255)))
        else:

            self.setBrush(QBrush(QColor(189, 232, 255)))

    def add_edge(self, edge):
        self.edges.append(edge)

    def remove_edge(self, edge):
        if edge in self.edges:
            self.edges.remove(edge)

    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemPositionHasChanged:
            for edge in self.edges:
                edge.update_position()
        return super(MyNode, self).itemChange(change, value)

    def mousePressEvent(self, event):
        row_num = max(len(self.parent_node), len(self.child_node), 1)
        new_data = [[''] * row_num for x in range(3)]
        new_data[0][0] = self.text.toPlainText()
        for index, x in enumerate(self.parent_node):
            new_data[1][index] = x.text.toPlainText()
        for index, x in enumerate(self.child_node):
            new_data[2][index] = x.text.toPlainText()

        new_data = [list(row) for row in zip(*new_data)]

        self.scene.parent.table_info_manager.update_table_data(new_data)
        super(MyNode, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        super(MyNode, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        super(MyNode, self).mouseReleaseEvent(event)

    def hoverEnterEvent(self, event):
        # 更改鼠标图标为手
        self.setCursor(QCursor(Qt.OpenHandCursor))
        super(MyNode, self).hoverEnterEvent(event)

    def hoverLeaveEvent(self, event):
        # 鼠标离开事件
        self.setCursor(QCursor(Qt.ArrowCursor))
        super(MyNode, self).hoverLeaveEvent(event)

    def contextMenuEvent(self, event):
        # 右键菜单事件
        # TODO: scene的右键点击事件先于node的右键点击事件执行,重写之后导致重复执行
        print("节点右键菜单事件")
        super(MyNode, self).contextMenuEvent(event)

    def mouseDoubleClickEvent(self, event):
        # 鼠标双击事件
        if isinstance(self, (RootNode, SubNode)):
            if self.child_node:  # 若有子节点则为非叶子节点
                dialog = NodeFormWindow()
                dialog.setWindowTitle(self.text.toPlainText() + '-权重配置')
                # TODO:这块配置完权重后，需要将其保存到文件中
                for child in self.child_node:
                    node_name_label = child.text.toPlainText()
                    node_name_edit = QLineEdit()
                    dialog.formLayout.addRow(node_name_label, node_name_edit)
                dialog.exec_()
            else:  # 若无子节点则为叶子节点
                dialog = LeafNodeFormWindow(self)
                dialog.setWindowTitle(self.text.toPlainText())
                dialog.setWindowIcon(QIcon(os.path.join(Config.svg_path, "leaf.svg")))
                dialog.exec_()



class RootNode(MyNode):
    def __init__(self, x, y, width, height, scene=None, plain_text='Root Node'):
        super(RootNode, self).__init__(x, y, width, height, scene, plain_text)
        small_width = 5
        small_height = 5

        # 计算小矩形的位置
        small_rect_bottom_x = (width - small_width) / 2
        small_rect_bottom_y = height - small_height

        # 创建上边的小矩形
        self.scene = scene
        self.small_rect_top = None
        self.small_rect_bottom = SmallRectNode(0, 0, small_width, small_height,
                                               self, self.scene)
        self.small_rect_bottom.setBrush(QBrush(QColor(150, 250, 100)))
        self.small_rect_bottom.setPos(small_rect_bottom_x, small_rect_bottom_y)


class SubNode(MyNode):
    def __init__(self, x, y, width, height, scene=None, plain_text='Sub Node'):
        super(SubNode, self).__init__(x, y, width, height, scene, plain_text)
        small_width = 5
        small_height = 5

        small_rect_top_x = (width - small_width) / 2
        small_rect_top_y = 0
        small_rect_bottom_x = (width - small_width) / 2
        small_rect_bottom_y = height - small_height
        self.scene = scene
        # 创建上边的小矩形
        self.small_rect_top = SmallRectNode(0, 0, small_width, small_height, self, self.scene, True)
        self.small_rect_top.setBrush(QBrush(QColor(250, 150, 100)))
        self.small_rect_top.setPos(small_rect_top_x, small_rect_top_y)

        # 创建下边的小矩形
        self.small_rect_bottom = SmallRectNode(0, 0, small_width, small_height,
                                               self, self.scene)
        self.small_rect_bottom.setBrush(QBrush(QColor(150, 250, 100)))
        self.small_rect_bottom.setPos(small_rect_bottom_x, small_rect_bottom_y)

    def update_small_node_pos(self, new_width, new_height):
        small_width = self.small_rect_top.rect().width()
        small_height = self.small_rect_top.rect().height()
        small_rect_top_x = (new_width - small_width) / 2
        small_rect_top_y = 0
        self.small_rect_top.setPos(small_rect_top_x, small_rect_top_y)
        small_rect_bottom_x = (new_width - small_width) / 2
        small_rect_bottom_y = new_height - small_height
        self.small_rect_bottom.setPos(small_rect_bottom_x, small_rect_bottom_y)


# 文本节点
class TextNode(QGraphicsTextItem):
    def __init__(self, text, node=None):
        super(TextNode, self).__init__(text, node)
        self.node = node
        self.setDefaultTextColor(Qt.blue)
        self.setFlag(QGraphicsTextItem.ItemIsSelectable)
        self.setFlag(QGraphicsTextItem.ItemIsFocusable)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            print("text 点击")
            self.setCursor(QCursor(Qt.IBeamCursor))
            self.setTextInteractionFlags(Qt.TextEditorInteraction)
            self.setFocus()
            self.node.mousePressEvent(event)
            super(TextNode, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        self.node.mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        self.node.mouseReleaseEvent(event)

    def mouseDoubleClickEvent(self, event):
        # 鼠标双击事件
        self.node.mouseDoubleClickEvent(event)

    def focusOutEvent(self, event):
        # 失去焦点时禁用文本编辑模式
        self.setTextInteractionFlags(Qt.NoTextInteraction)
        self.setCursor(QCursor(Qt.OpenHandCursor))
        print("text 失去焦点")
        super(TextNode, self).focusOutEvent(event)
